xm: New command 'debug-keys' to inject debug-key events into Xen.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 9 Mar 2007 11:11:59 +0000 (11:11 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 9 Mar 2007 11:11:59 +0000 (11:11 +0000)
Signed-off-by: Keir Fraser <keir@xensource.com>
tools/libxc/xc_misc.c
tools/libxc/xenctrl.h
tools/python/xen/lowlevel/xc/xc.c
tools/python/xen/xend/XendNode.py
tools/python/xen/xend/server/XMLRPCServer.py
tools/python/xen/xm/main.py
xen/common/keyhandler.c
xen/common/sysctl.c
xen/include/public/sysctl.h

index b2a648528a2dc3e4fda85957af5efbfad0ce31df..987eb0eb1336774923bcaa44675699954c8f8039 100644 (file)
@@ -33,6 +33,25 @@ int xc_readconsolering(int xc_handle,
     return ret;
 }
 
+int xc_send_debug_keys(int xc_handle, char *keys)
+{
+    int ret, len = strlen(keys);
+    DECLARE_SYSCTL;
+
+    sysctl.cmd = XEN_SYSCTL_debug_keys;
+    set_xen_guest_handle(sysctl.u.debug_keys.keys, keys);
+    sysctl.u.debug_keys.nr_keys = len;
+
+    if ( (ret = lock_pages(keys, len)) != 0 )
+        return ret;
+
+    ret = do_sysctl(xc_handle, &sysctl);
+
+    unlock_pages(keys, len);
+
+    return ret;
+}
+
 int xc_physinfo(int xc_handle,
                 xc_physinfo_t *put_info)
 {
index 96ba3145034b87e9b0933d1e630d0425ae037ebc..4b346a74f09e07c2052d8cb04f27958ebbbf97f8 100644 (file)
@@ -467,6 +467,8 @@ int xc_readconsolering(int xc_handle,
                        unsigned int *pnr_chars,
                        int clear);
 
+int xc_send_debug_keys(int xc_handle, char *keys);
+
 typedef xen_sysctl_physinfo_t xc_physinfo_t;
 int xc_physinfo(int xc_handle,
                 xc_physinfo_t *info);
index 7da0288cbd04ff0c0c61e61c113de6cd51ce0357..804adc31045973c51d9bf441ed021c70dfbd6407 100644 (file)
@@ -1007,6 +1007,24 @@ static PyObject *pyxc_domain_send_trigger(XcObject *self,
     return zero;
 }
 
+static PyObject *pyxc_send_debug_keys(XcObject *self,
+                                      PyObject *args,
+                                      PyObject *kwds)
+{
+    char *keys;
+
+    static char *kwd_list[] = { "keys", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "s", kwd_list, &keys) )
+        return NULL;
+
+    if ( xc_send_debug_keys(self->xc_handle, keys) != 0 )
+        return pyxc_error_to_exception();
+
+    Py_INCREF(zero);
+    return zero;
+}
+
 static PyObject *dom_op(XcObject *self, PyObject *args,
                         int (*fn)(int, uint32_t))
 {
@@ -1420,6 +1438,12 @@ static PyMethodDef pyxc_methods[] = {
       " vcpu    [int]: VCPU to be sent trigger.\n"
       "Returns: [int] 0 on success; -1 on error.\n" },
 
+    { "send_debug_keys",
+      (PyCFunction)pyxc_send_debug_keys,
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Inject debug keys into Xen.\n"
+      " keys    [str]: String of keys to inject.\n" },
+
 #ifdef __powerpc__
     { "arch_alloc_real_mode_area", 
       (PyCFunction)pyxc_alloc_real_mode_area, 
index 9d2a70dd9e9a6d17bc451f56afaa269798f02cf2..5976d80f397e0a0eda88d9b4ccd35791c0ab0bb3 100644 (file)
@@ -453,6 +453,12 @@ class XendNode:
                 return pif.network
         raise Exception('Bridge %s is not connected to a network' % bridge)
 
+    #
+    # Debug keys.
+    #
+
+    def send_debug_keys(self, keys):
+        return self.xc.send_debug_keys(keys)
 
     #
     # Getting host information.
index 7c3a2a1a9d0c2733b236d059ee3be4bc1ba59d80..ed07811ff6d1d7817798d958ba1bb6801d38234f 100644 (file)
@@ -157,7 +157,7 @@ class XMLRPCServer:
                     self.server.register_function(fn, "xend.domain.%s" % name[7:])
 
         # Functions in XendNode and XendDmesg
-        for type, lst, n in [(XendNode, ['info'], 'node'),
+        for type, lst, n in [(XendNode, ['info', 'send_debug_keys'], 'node'),
                              (XendDmesg, ['info', 'clear'], 'node.dmesg')]:
             inst = type.instance()
             for name in lst:
index 7075e95444c059ce221e89455662ce92df1b7440..8fcc2bc525597966c776a05357a614c4e914cae3 100644 (file)
@@ -133,6 +133,7 @@ SUBCOMMAND_HELP = {
     'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
                      'Get/set credit scheduler parameters.'),
     'sysrq'       : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
+    'debug-keys'  : ('<Keys>', 'Send debug keys to Xen.'),
     'trigger'     : ('<Domain> <nmi|reset|init> [<VCPU>]',
                      'Send a trigger to a domain.'),
     'vcpu-list'   : ('[<Domain>]',
@@ -260,7 +261,6 @@ common_commands = [
     "shutdown",
     "start",
     "suspend",
-    "trigger",
     "top",
     "unpause",
     "uptime",
@@ -300,6 +300,7 @@ domain_commands = [
     ]
 
 host_commands = [
+    "debug-keys",
     "dmesg",
     "info",
     "log",
@@ -1395,6 +1396,10 @@ def xm_trigger(args):
     
     server.xend.domain.send_trigger(dom, trigger, vcpu)
 
+def xm_debug_keys(args):
+    arg_check(args, "debug-keys", 1)
+    server.xend.node.send_debug_keys(str(args[0]))
+
 def xm_top(args):
     arg_check(args, "top", 0)
 
@@ -1738,6 +1743,7 @@ commands = {
     "pause": xm_pause,
     "unpause": xm_unpause,
     # host commands
+    "debug-keys": xm_debug_keys,
     "dmesg": xm_dmesg,
     "info": xm_info,
     "log": xm_log,
index b99d396399808db483adfbf90584a08f920e907f..da92b6fdedeb2dbe9a2a969d5c96c75a6d80950a 100644 (file)
@@ -47,7 +47,7 @@ void handle_keypress(unsigned char key, struct cpu_user_regs *regs)
 {
     irq_keyhandler_t *h;
 
-    if ( key_table[key].flags & KEYHANDLER_IRQ_CALLBACK )
+    if ( !in_irq() || (key_table[key].flags & KEYHANDLER_IRQ_CALLBACK) )
     {
         console_start_log_everything();
         if ( (h = key_table[key].u.irq_handler) != NULL )
index 789e643ff249f3360c628ba81d6f62b241930922..0cba2c1164d4358dceaee383d7590803b9a9c321 100644 (file)
@@ -18,6 +18,7 @@
 #include <xen/console.h>
 #include <xen/iocap.h>
 #include <xen/guest_access.h>
+#include <xen/keyhandler.h>
 #include <asm/current.h>
 #include <public/sysctl.h>
 
@@ -121,6 +122,20 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
     break;
 #endif
 
+    case XEN_SYSCTL_debug_keys:
+    {
+        char c;
+        uint32_t i;
+
+        for ( i = 0; i < op->u.debug_keys.nr_keys; i++ )
+        {
+            if ( copy_from_guest_offset(&c, op->u.debug_keys.keys, i, 1) )
+                return -EFAULT;
+            handle_keypress(c, guest_cpu_user_regs());
+        }
+    }
+    break;
+
     default:
         ret = arch_do_sysctl(op, u_sysctl);
         break;
index dcd7ee7d2626f09ae672ccee907e45469e8b1146..e18d7243f6493ff8457a371237fbc699f5129b3d 100644 (file)
@@ -140,6 +140,18 @@ struct xen_sysctl_getdomaininfolist {
 typedef struct xen_sysctl_getdomaininfolist xen_sysctl_getdomaininfolist_t;
 DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getdomaininfolist_t);
 
+/*
+ * Inject debug keys into Xen.
+ */
+#define XEN_SYSCTL_debug_keys        7
+struct xen_sysctl_debug_keys {
+    /* IN variables. */
+    XEN_GUEST_HANDLE_64(char) keys;
+    uint32_t nr_keys;
+};
+typedef struct xen_sysctl_debug_keys xen_sysctl_debug_keys_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_debug_keys_t);
+
 struct xen_sysctl {
     uint32_t cmd;
     uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */
@@ -150,6 +162,7 @@ struct xen_sysctl {
         struct xen_sysctl_sched_id          sched_id;
         struct xen_sysctl_perfc_op          perfc_op;
         struct xen_sysctl_getdomaininfolist getdomaininfolist;
+        struct xen_sysctl_debug_keys        debug_keys;
         uint8_t                             pad[128];
     } u;
 };